//
//  SQLiteHelper.m
//  SQLiteHelper
//
//  Created by Ryou Zhang on 8/30/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "SQLiteHelper.h"
#import "FMDatabase.h"
#import "DBQueryObject.h"


@interface SQLiteHelper(PrivateMethod)
-(void)closeDatabase;
-(void)moniterSQLiteDB;
-(void)moniterSQLiteDBUpdate;

-(void)executeDBQuery:(DBQueryObject*)queryObj;
-(void)syncExecuteDBUpdate:(DBQueryObject*)queryObj;
-(void)asynExecuteDBUpdate:(DBQueryObject*)queryObj;
@end


@implementation SQLiteHelper
static SQLiteHelper* m_Instance = nil;
+(SQLiteHelper*)getInstance
{
	if (m_Instance == nil)
		m_Instance = [SQLiteHelper new];
	return m_Instance;
}

-(id)init
{
    self = [super init];
    if (self) {
        threadFlag = YES;
		dbMoniter = [[NSThread alloc] initWithTarget:self selector:@selector(moniterSQLiteDB) object:nil];
		[dbMoniter start];
    }
    return self;
}

-(BOOL)openDatabase:(NSString*)dbPath
{
	assert(db == nil);
	
	db=[[FMDatabase alloc] initWithPath:dbPath];
	if ([db open]) 
	{
		[db setShouldCacheStatements:NO];
		
		return YES;
	}else
		return NO;
}

-(void)closeDatabase
{
	if (db!=nil)
	{
		[db close];
		SafeRelease(db);
	}	
}

-(FMResultSet*)syncExecuteQuery:(NSString*)sql
{
	DBQueryObject* obj = [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= nil;
	
	[self performSelector:@selector(executeDBQuery:) onThread:dbMoniter withObject:obj waitUntilDone:YES];
	
	FMResultSet* result = obj->queryResult;
	[result retain];
	SafeRelease(obj);
	
	return [result autorelease];
}

-(FMResultSet*)syncExecuteQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
{
	DBQueryObject* obj = [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= [arguments retain];
	[self performSelector:@selector(executeDBQuery:) onThread:dbMoniter withObject:obj waitUntilDone:YES];
	
	FMResultSet* result = obj->queryResult;
	[result retain];
	SafeRelease(obj);
	
	return [result autorelease];
}

-(void)executeDBQuery:(DBQueryObject*)queryObj
{
	id target = [db executeQuery:queryObj->queryString withArgumentsInArray:queryObj->arguments];
	queryObj->queryResult = target;
	[queryObj->queryResult retain];
}

-(void)asynExecuteUpdate:(NSString*)sql
{
	DBQueryObject* obj	= [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= nil;
	
	[self performSelector:@selector(asynExecuteDBUpdate:) onThread:dbMoniter withObject:obj waitUntilDone:NO];
}

-(void)asynExecuteUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
{
	DBQueryObject* obj	= [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= [arguments retain];
	
	[self performSelector:@selector(asynExecuteDBUpdate:) onThread:dbMoniter withObject:obj waitUntilDone:NO];	
}

-(BOOL)syncExecuteUpdate:(NSString*)sql
{
	DBQueryObject* obj	= [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= nil;
	
	[self performSelector:@selector(syncExecuteDBUpdate:) onThread:dbMoniter withObject:obj waitUntilDone:YES];	
	
	BOOL result = [(NSNumber*)obj->queryResult boolValue];
	SafeRelease(obj);
	
	return result;
}
-(BOOL)syncExecuteUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
{
	DBQueryObject* obj	= [DBQueryObject new];
	obj->queryString	= [sql retain];
	obj->arguments		= [arguments retain];
	
	[self performSelector:@selector(syncExecuteDBUpdate:) onThread:dbMoniter withObject:obj waitUntilDone:YES];
	
	BOOL result = [(NSNumber*)obj->queryResult boolValue];
	SafeRelease(obj);
	
	return result;
}


-(void)syncExecuteDBUpdate:(DBQueryObject*)queryObj
{
	BOOL result = [db executeUpdate:queryObj->queryString withArgumentsInArray:queryObj->arguments];
	queryObj->queryResult = [NSNumber numberWithBool:result];
}

-(void)asynExecuteDBUpdate:(DBQueryObject*)queryObj
{
	[db executeUpdate:queryObj->queryString withArgumentsInArray:queryObj->arguments];
	SafeRelease(queryObj);
}

-(void)moniterSQLiteDB
{
	NSAutoreleasePool* pool = [NSAutoreleasePool new];
	
	NSRunLoop* loop = [NSRunLoop currentRunLoop];
	
	NSTimer* timer = [[NSTimer alloc] initWithFireDate:nil
											  interval:1
												target:self
											  selector:@selector(moniterSQLiteDBUpdate)
											  userInfo:nil
											   repeats:YES];
	
	[loop addTimer:timer forMode:NSDefaultRunLoopMode];
	
	while(threadFlag & [loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
	
	[timer invalidate];
	SafeRelease(timer);
	SafeRelease(pool);
	[NSThread exit];
}

-(void)moniterSQLiteDBUpdate
{
	//do nothing
}

-(void)dealloc
{
	threadFlag = NO;
	dbMoniter = nil;
	[self closeDatabase];
	[super dealloc];
}
@end
